package ncc.bs.Plugins;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.NCLocator;
import nc.itf.pub.dbservice.IDBService;
import nc.jdbc.framework.generator.IdGenerator;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDouble;
import nccloud.bs.log.LogVO;
import nccloud.framework.service.ServiceLocator;
import nccloud.pubitf.gl.account.IAccountReportWebService;
import nccloud.pubitf.gl.lightgl.voucher.init.IInitWebService;
import nccloud.utils.baseapp.GetDateUtil;
import nccloud.utils.baseapp.HttpReqUtils;
import nccloud.utils.baseapp.InitParamUtils;
import nccloud.utils.baseapp.MessageLogger;
import nccloud.utils.baseapp.ToolUtils;

/** 
 * <p>同步财政系统</p>
 * 单位会计余额发生额汇总表
 * @author Administrator
 * @date 2024年03月05日
 */
public class AccountBalanceBackGroundWorkPlugin extends AbstractBackgroundWorkPlugin{
	private BaseDAO dao;
	private final SimpleDateFormat ymd = new SimpleDateFormat("yyyy-MM-dd");
	private final SimpleDateFormat ymdsfm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	private IDBService dbService;
	private IInitWebService initWebService;// 科目余额查询服务

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void doBusiness(Map keyMap) throws BusinessException {
		try {
			Map<String, Object> queryParam = setQueryParam(keyMap);
			if(queryParam == null) return;
			Map<String, Object> datas = this.getInitWebService().getInitMap("1001A210000000000R84", queryParam.get("startyear").toString(), queryParam.get("startperiod").toString(),
					queryParam.get("startdate").toString(), "账簿本币", new String[]{}, new String[]{}, false, "20020401PAGE");
			List<Map<String,Object>> datalists  = (ArrayList<Map<String,Object>>)datas.get("initvos");
//			Object data = ""; //queryAccBalance.get("data");
//			if(data == null) return;
			List<List<Map<String,Object>>> listparams = super.getGroupAfterData(datalists);
			// 对分组的数据进行推送
			for(List<Map<String, Object>> params : listparams) {
				List<LogVO> listVOs = new ArrayList<>();
				String message = null;
				String issuccess = "Y";
				String result = null;
				try {
					String param = super.getParam(buildParam(queryParam, params,listVOs),"DWKJHS07", super.getAppid()); // 每十行数据合并在一起推送
					if(param == null || "".equals(param)) return;
					result = HttpReqUtils.sendPost(getURL("DEF001"), param);
					MessageLogger.info("----第四步接口响应结果::" + result);
					JSONObject jsonres = JSONObject.parseObject(result);
					Object code = jsonres.get("code");
					if("200".equals(code)) {
						message = "同步成功";
					}else {
						message = jsonres.getString("msg"); 
						issuccess = "N";
						result = jsonres.toString();
					}
					
				}catch(Exception e) {
					message = e.getMessage();
					issuccess = "N";
				}finally {
					for(LogVO vo : listVOs) {
						vo.setIssuccess(issuccess);
						vo.setError(message);
						vo.setVdef2(result);
						vo.setDr("0");
						
					}
					getDbService().insertVOList(listVOs);
				}
			}
		}catch(Exception e) {
			LogVO vo = new LogVO();
			vo.setPk_id(NCLocator.getInstance().lookup(IdGenerator.class).generate());
			vo.setIssuccess("N");
			vo.setPk_group("0001A210000000000JB9");
			vo.setPk_billtypeid("accountBalance");
			vo.setSystem_flag("financial");
			vo.setVdef1("拉取参数、类型:"+ keyMap.get("type")+",开始日期:"+keyMap.get("begindate")+"结束日期:"+keyMap.get("enddate")+",同步频率:"+keyMap.get("synctime"));
			vo.setError("会计科目同步:"+e.getMessage());
			getDbService().insertVO(vo);
		}
	}
	
	/**
	 * 设置会计科目查询参数
	 * @param keyMap
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public Map<String,Object> setQueryParam(Map keyMap) throws BusinessException{
		Map<String, Object> param = new HashMap<>();
		List<Object> accountbooks = new ArrayList<Object>();
		Object orgCode = keyMap.get("org");
		String startdate = ""; // 2024-03-01
		String enddate = ""; // 2024-03-31 23:59:59
		String startyear = ""; // 2024
		String startperiod = ""; // 03
		String endyear = ""; // 2024
		String endperiod = ""; // 03
		if(orgCode == null || "".equals(orgCode)) {
			Object pk_org = getDao().executeQuery("select pk_accountingbook from org_accountingbook where dr = 0 and code = '00101-0002'", new ColumnProcessor());
			accountbooks.add(pk_org);
		}else {
			Object pk_org = getDao().executeQuery("select pk_accountingbook from org_accountingbook where dr = 0 and code = '"+orgCode+"-0002' ", new ColumnProcessor());
			if(pk_org == null) return null;
			accountbooks.add(pk_org);
		}
		Object type = keyMap.get("type");
		if("1".equals(type)) { //  [指定时间段拉取,1];[拉指定的一天,2];
			startdate = keyMap.get("begindate")  == null  ? ymd.format(new Date()) : keyMap.get("begindate").toString() ;
			enddate = keyMap.get("enddate") == null  ? ymdsfm.format(new Date()) : keyMap.get("enddate").toString()+" 23:59:59" ;
		}else if("2".equals(type)) { // [拉指定的一天,2]
			startdate = keyMap.get("begindate") == null  ? ymd.format(new Date()) : keyMap.get("begindate").toString() ;
			enddate =  startdate+" 23:59:59";
		}else { // [定时执行, ] 默认同步频率30分钟  
//			ymd.format("")
			startdate = GetDateUtil.getFistDay(new UFDate());
			enddate = GetDateUtil.getLastDay(new UFDate());
		}
		String[] startdates = startdate.split("-");
		startyear = startdates[0];startperiod = startdates[1];
		String[] enddates = enddate.split("-");
		endyear = enddates[0];endperiod = enddates[1];
		param.put("pk_accountingbook" , accountbooks);
		param.put("pk_unit" , new ArrayList());
		param.put("pk_liabilitycenter" ,new ArrayList<>());
		param.put("qryObjs" ,new ArrayList<>());
		param.put("multbusi" ,UFBoolean.FALSE);
		param.put("multliabcenter" , UFBoolean.FALSE);
		param.put("usesubjversion" ,"N");
		param.put("versiondate" ,null);
		param.put("subjVersionShow" ,"0000-00-00");
		param.put("startlvl" ,"1");
		param.put("endlvl" ,"8");
		param.put("isleave" ,"N");
		param.put("isoutacc" ,"N");
		param.put("startyear" ,startyear);
		param.put("endyear" ,endyear);
		param.put("startperiod" , startperiod);
		param.put("endperiod" ,endperiod);
		param.put("startdate" ,startdate);
		param.put("enddate" ,enddate);
		param.put("multiYearMerge" , UFBoolean.FALSE);
		param.put("includeuntally" ,"Y");
		param.put("includeerror" ,"Y");
		param.put("includeplcf" ,"Y");
		param.put("includerc" ,"N");
		param.put("pk_currtype" ,"本币");
		param.put("returncurr" ,"1");
		param.put("mutibook" ,"N");
		param.put("showzerooccur" ,"N");
		param.put("showzerobalance" ,"N");
		param.put("showzerobalanceoccur" ,"Y");
		param.put("currplusacc" ,"Y");
		param.put("sumbysubjtype" ,"N");
		param.put("balanceori" ,"-1");
		param.put("twowaybalance" ,"N");
		param.put("querybyperiod" ,"true");
		param.put("pk_accasoa" ,new ArrayList<>());
		param.put("pk_fccurrtype","");
		param.put("fcrate" ,"");
		param.put("subjectType","0");
		param.put("returnSubjectType","1");
		param.put("appcode","20023005");

		return param;
	}

	/**
	 * 查询需要同步的数据
	 * @param sql
	 * @return
	 * @throws BusinessException
	 */
	public List<Map<String, Object>>  queryData(String sql)  throws BusinessException{
		return null;
	}
	
	/**
	 * 构建数据查询sql
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("rawtypes")
	public String buildSQL(Map keyMap) throws BusinessException{
		return null;
	}
	
	/**
	 * 构建请求参数
	 * @param queParam 查询科目余额参数
	 * @param data 推送三方的数据
	 * @param listVOs
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public JSONArray buildParam(Map<String, Object> queParam,List<Map<String, Object>> data,List<LogVO> listVOs) throws Exception{
		if(data == null) return null;
		JSONArray jsonArray = new JSONArray();
		for(Map<String, Object> map : data) {
			JSONObject json = new JSONObject();
			Map<String, Object> endlocalamount = (Map<String, Object>)map.get("endlocalamount");// 期初
			if(new UFDouble(endlocalamount.get("value").toString()).getDouble() == new UFDouble(0).getDouble()) continue;
			List<Map<String, Object>> accAssItems = (List<Map<String, Object>>)map.get("accAssItems");
			if(accAssItems != null && accAssItems.size() > 0){
				for(Map<String, Object> accAssItem : accAssItems){
					Object code = accAssItem.get("code");// 辅助代码
					List<Map<String, Object>> lists = this.getDefdocDZ("CG_0001", code);
					if(lists != null){
						Map<String, Object> imap = lists.get(0);
						String iCode = imap.get("code").toString();
						json.put(iCode, code);
					}
				}
			}
			String pk = queParam.get("startyear").toString()+queParam.get("startperiod")+queParam.get("endperiod")+map.get("assname");
			String sql = "select vdef4 from  SYNC_FINANCIAL_LOG where issuccess = 'Y' and Vdef3 = '"+pk+"'";
			Object pkvdef3 = getDao().executeQuery(sql, new ColumnProcessor());
			Object bal_id = pkvdef3 == null ? UUID.randomUUID() : pkvdef3;
			json.put("BAL_ID", bal_id); // 凭证分录唯一标识
			json.put("MOF_DIV_CODE", super.getMOF_DIV_CODE()); // 财政区划代码
			json.put("SET_YEAR", queParam.get("startyear")); // // 会计年度
			json.put("AGENCY_CODE", super.getUnit()); // 单位代码
			json.put("ACCT_SET_CODE", super.getAccount());  // 账套编号
			json.put("ACCT_SET_NAME", super.getACCT_SET_NAME());  // 账套名称
			json.put("AGENCY_NAME", super.getAGENCY_NAME()); // 单位名称
			json.put("ACCT_PERIOD", 0); //会计期间
			Map<String, Object> accountCodemap = (Map<String, Object>)map.get("accountCode");
			Object accountCode = accountCodemap.get("display");
			json.put("GOV_ACCT_CLS_CODE", accountCode); // 单位会计科目代码
			Map<String, Object> balanorient = (Map<String, Object>)map.get("balanorient"); // 借贷方向 借:0 贷方 :1
			UFDouble value = new UFDouble(endlocalamount.get("value").toString());
			BigDecimal amt = BigDecimal.valueOf(value.getDouble()).setScale(4, RoundingMode.HALF_UP);
            if("0".equals(balanorient.get("value").toString())) {// 借方
				json.put("QTY_DR_AMT", 0); // 借方数量
				json.put("QTY_CR_AMT", 0); // 贷方数量
				json.put("CR_AMT", 0);  // 财务贷方
				json.put("DR_AMT", amt); // 财务借方
			}else if (!"1".equals(balanorient.get("value").toString())){
				json.put("CR_AMT", 0);  // 财务贷方
				json.put("DR_AMT", 0); // 财务借方
				json.put("QTY_DR_AMT", 0); // 借方数量
				json.put("QTY_CR_AMT", 0); // 贷方数量
			}else { // 贷
				json.put("CR_AMT", amt);  // 财务贷方
				json.put("DR_AMT", 0); // 财务借方
				json.put("QTY_CR_AMT", 0); // 贷方数量
				json.put("QTY_DR_AMT", 0); // 借方数量
			}
			json.put("FOREIGN_DR_AMT",null);
			json.put("AGENCY_ACCT_VOUCHER_TYPE", queParam.get("startperiod"));
			json.put("FOREIGN_CR_AMT",0);
			json.put("CURRENCY_CODE", "CNY"); // 币种代码
			json.put("UPDATE_TIME", super.getYMDHMS(map.get("update_time"))); // 更新时间
			json.put("CREATE_TIME", super.getYMDHMS(map.get("create_time")));
			json.put("IS_DELETED", 2); // 1已删除 2 未删除
			json.put("FOREIGN_DR_AMT", 0);
//			json.put("DEP_BGT_ECO_CODE", ""); //
//			json.put("FUND_TYPE_CODE","111");
//			json.put("FATYPE_CODE", "");
//			json.put("SUP_BGT_DOC_NO", "");
//			json.put("MOF_DEP_CODE", "");
//			json.put("ORI_PRO_CODE", "");
//			json.put("FUND_TRAOBJ_TYPE_CODE", "");
//			json.put("GOV_BGT_ECO_CODE", "");
//			json.put("COR_BGT_DOC_NO", "");
//			json.put("FUND_TRA_OBJ_NAME", "");
//			json.put("SET_MODE_CODE", "");
//			json.put("PAY_TYPE_CODE", "");
//			json.put("COST_TYPE_CODE", "");
//			json.put("FUND_TRA_OBJ_NO", "");
//			json.put("BUDGET_LEVEL_CODE", "");
//			json.put("BGT_TYPE_CODE", "");
//			json.put("DUE_DATE", "");
//			json.put("FOUND_TYPE_CODE", "");
//			json.put("PUR_MET_CODE", "");
//			json.put("PAY_BUS_TYPE_CODE", "");
//			json.put("PRO_CODE","");      // 项目代码
//			json.put("EXP_FUNC_CODE",""); // 部门支出经济分类代码
			LogVO logVO = getDbService().buildLogVO(map, json, "financial", "accountBalance");
			logVO.setVdef3(pk);
			logVO.setVbillcode(bal_id.toString());
			listVOs.add(logVO);
			jsonArray.add(json);
		}
		return jsonArray;
	}

	/**
	 * 获取基础数据对找关系
	 * @param defCode
	 * @param ncCode
	 * @return
	 * @throws BusinessException
	 */
	protected  List<Map<String, Object>> getDefdocDZ(Object defCode,Object ncCode) throws BusinessException{
		String sql = this.buildDefdocDZ(defCode, ncCode);
		List<Map<String, Object>> lists = (List<Map<String, Object>>)getDao().executeQuery(sql, new MapListProcessor());
		if(lists != null && lists.size() > 0){
			return lists;
		}
		return null;
	}

	/**
	 * 构建自定义档案查询sql
	 * @param defCode 自定义档案编码 -- CG_0001
	 * @param ncCode  档案编码 (简称)
	 * @return
	 * @throws BusinessException
	 */
	protected String buildDefdocDZ(Object defCode, Object ncCode) throws BusinessException{
        String sql = "select  " +
                "    bd_defdoc.code, bd_defdoc.name, bd_defdoc.mnecode,bd_defdoc.shortname " +
                "from bd_defdoc " +
                "left join bd_defdoclist  on bd_defdoc.pk_defdoclist = bd_defdoclist.pk_defdoclist " +
                "left join org_orgs on org_orgs.pk_org = bd_defdoc.pk_org " +
                "where bd_defdoc.dr = 0 " +
                "      and bd_defdoc.enablestate = 2 " +
                "      and bd_defdoclist.dr = 0 " +
                "      and org_orgs.dr = 0 " +
                "      and bd_defdoclist.code='" + defCode + "' " +
                "      and bd_defdoc.shortname = '" + ncCode + "' ";
		return sql;
	}




	/**
	 * 获取第三方同步地址
	 * @param initCode
	 * @return
	 * @throws Exception
	 */
	public String getURL(String initCode) throws Exception{
		String url = InitParamUtils.getOrgParam("GLOBLE00000000000000",initCode)+"/pty/gla-dec/v1/voucher/balances";
		MessageLogger.info("----第三步接口请求地址:" + url);
		return url;
	}

	/**
	 * 数据库操作服务
	 * @return
	 */
	public IDBService getDbService() {
		if(dbService == null) {
			dbService = NCLocator.getInstance().lookup(IDBService.class);
		}
		return dbService;
	}

	public IInitWebService getInitWebService() {
		if (null == this.initWebService){
			this.initWebService = NCLocator.getInstance().lookup(IInitWebService.class);
		}
		return this.initWebService;
	}

	public void setInitWebService(IInitWebService initWebService) {
		this.initWebService = initWebService;
	}

	public BaseDAO getDao() {
		return dao == null ? new BaseDAO() : dao ;
	}
}
